home *** CD-ROM | disk | FTP | other *** search
/ Nautilus 1993 March / Nautilus-4-3 / Nautilus-4-3.bin / Multimedia / Feature / RlePict1.1 Folder / lib / rle_putrow.c < prev    next >
Encoding:
C/C++ Source or Header  |  1992-05-08  |  17.7 KB  |  727 lines

  1. /*
  2.  * This software is copyrighted as noted below.  It may be freely copied,
  3.  * modified, and redistributed, provided that the copyright notice is 
  4.  * preserved on all copies.
  5.  * 
  6.  * There is no warranty or other guarantee of fitness for this software,
  7.  * it is provided solely "as is".  Bug reports or fixes may be sent
  8.  * to the author, who may or may not act on them as he desires.
  9.  *
  10.  * You may not include this software in a program or other software product
  11.  * without supplying the source, or without informing the end-user that the 
  12.  * source is available for no extra charge.
  13.  *
  14.  * If you modify this software, you should include a notice giving the
  15.  * name of the person performing the modification, the date of modification,
  16.  * and the reason for such modification.
  17.  *
  18.  *  Modified at BRL 16-May-88 by Mike Muuss to avoid Alliant STDC desire
  19.  *  to have all "void" functions so declared.
  20.  */
  21. /* 
  22.  * rle_putrow.c - Save a row of the fb to a file.
  23.  * 
  24.  * Author:    Spencer W. Thomas
  25.  *         Computer Science Dept.
  26.  *         University of Utah
  27.  * Date:    1 April 1981
  28.  * Copyright (c) 1981,1986 Spencer W. Thomas
  29.  *
  30.  * $Id: rle_putrow.c,v 3.0.1.2 1992/01/28 18:29:22 spencer Exp $
  31.  */
  32.  
  33. #include "stdio.h"
  34. #include "rle_put.h"
  35. #include "rle.h"
  36.  
  37. static int findruns();
  38.  
  39. #define FASTRUNS        /* Faster run finding */
  40. #ifdef vax
  41. #define LOCC            /* Use vax instructions for more speed */
  42. #endif
  43.  
  44. #define    FALSE    0
  45. #define    TRUE    1
  46.  
  47. /* Save some typing. */
  48. #define PBRUN the_hdr->priv.put.brun
  49.  
  50. /*****************************************************************
  51.  * TAG( rle_putrow )
  52.  * Write a scanline to the output file.
  53.  * 
  54.  * Inputs:
  55.  *    rows:        Pointer to vector of pointers to
  56.  *            rle_pixel arrays containing the pixel information.
  57.  *            If NULL, rowlen scanlines are skipped.
  58.  *    rowlen:        The number of pixels in the scanline, or the
  59.  *            number of scanlines to skip (see above).
  60.  * Outputs:
  61.  *     Run length encoded information is written to the_hdr.rle_file.
  62.  * Assumptions:
  63.  *     I'm sure there are lots of assumptions in here.
  64.  * Algorithm:
  65.  *     There are two parts:
  66.  *         1. Find all "sufficiently long" runs of background
  67.  *            color.  These will not be saved at all.
  68.  *         2. For each run of non-background, for each color
  69.  *            channel, find runs of identical pixel values
  70.  *            between "data" segments (of differing pixel
  71.  *            values).
  72.  *     For part 1, "sufficiently long" is 2 pixels, if the following
  73.  *     data is less than 256 pixels long, otherwise it is 4 pixels.
  74.  *     This is enforced by a post-process merge.
  75.  *
  76.  *     Part 1 can be done in two different ways, depending on whether
  77.  *     FASTRUNS is defined or not.  With FASTRUNS defined, it finds
  78.  *     runs of the background pixel value in each channel
  79.  *     independently, and then merges the results.  With FASTRUNS not
  80.  *     defined, it scans all channels in parallel.
  81.  *
  82.  *     Part 2 uses a state machine.  For each run of non-background
  83.  *     data, it searches for sufficiently long sequences of a single
  84.  *     value (in each channel independently).  Sufficiently long is 4
  85.  *     pixels if the following data is < 256 pixels, 6 pixels
  86.  *     otherwise.  This is because the startup cost for the run is 2
  87.  *     bytes, and the startup cost for a data segment is 2 bytes if
  88.  *     it is < 256 pixels long, 4 bytes otherwise.  Thus a run
  89.  *     shorter than 4 or 6 pixels (respectively) would actually make
  90.  *     the output longer.  An additional pixel is required if the
  91.  *     preceding data is an odd number of pixels long (because a
  92.  *     filler byte will be output at the end of it.)
  93.  */
  94.  
  95. void
  96. rle_putrow(rows, rowlen, the_hdr)
  97. register rle_pixel *rows[];
  98. int rowlen;
  99. register rle_hdr * the_hdr;
  100. {
  101.     register int i, j;
  102.     int nrun;
  103.     register rle_pixel *row;
  104.     int mask;
  105.     char bits[256];
  106.     short   state,        /* State of run-finding state machine. */
  107.         dstart,        /* Starting point for current data segment. */
  108.             dend,        /* Ending point of current data segment. */
  109.         rstart = 0,        /* Starting point of current run. */
  110.         runval = 0;        /* Data value for current run. */
  111.  
  112.     if (rows == NULL)
  113.     {
  114.     the_hdr->priv.put.nblank += rowlen;
  115.     return;
  116.     }
  117.     /* 
  118.      * If not done already, allocate space to remember runs of
  119.      * non-background color.  A run of bg color must be at least 2
  120.      * bytes long to count, so there can be at most rowlen/3 of them.
  121.      */
  122.     if ( PBRUN == NULL )
  123.     {
  124.     PBRUN = (short (*)[2])malloc(
  125.         (unsigned)((rowlen/3 + 1) * 2 * sizeof(short)) );
  126.     if ( PBRUN == NULL )
  127.     {
  128.         fprintf( stderr, "%s: Malloc failed in rle_putrow, writing %s\n",
  129.              the_hdr->cmd, the_hdr->file_name );
  130.         exit(1);
  131.     }
  132.     }
  133.     /* Unpack bitmask in the_hdr struct */
  134.     for ( i=0; i < the_hdr->ncolors; i++ )
  135.     bits[i] = RLE_BIT( *the_hdr, i );
  136.     bits[255] = RLE_BIT( *the_hdr, -1 );
  137.  
  138.     /* 
  139.      * If saving only non-background pixels, find runs of them.  Note
  140.      * that the alpha channel is considered to be background iff it is
  141.      * zero.
  142.      */
  143. #ifdef    FASTRUNS
  144.     if ( the_hdr->background )
  145.     {
  146.     /* 
  147.      * Find runs in each color individually, merging them as we go.
  148.      */
  149.     nrun = 0;        /* start out with no runs */
  150.     /* Alpha channel first */
  151.     if ( the_hdr->alpha )
  152.         nrun = findruns( rows[-1], rowlen, 0, nrun, PBRUN );
  153.     /* Now the color channels */
  154.     for ( i = 0; i < the_hdr->ncolors; i++ )
  155.         if ( bits[i] )
  156.         nrun = findruns( rows[i], rowlen, the_hdr->bg_color[i],
  157.                  nrun, PBRUN );
  158.     }
  159.     else
  160.     {
  161.     PBRUN[0][0] = 0;
  162.     PBRUN[0][1] = rowlen-1;
  163.     nrun = 1;
  164.     }
  165. #else                /* FASTRUNS */
  166.     if (the_hdr->background)    /* find non-background runs */
  167.     {
  168.     j = 0;
  169.     for (i=0; i<rowlen; i++)
  170.         if (!same_color( i, rows, the_hdr->bg_color,
  171.                  the_hdr->ncolors, bits ) ||
  172.         (the_hdr->alpha && rows[-1][i] != 0))
  173.         {
  174.         if (j > 0 && i - PBRUN[j-1][1] <= 2)
  175.             j--;
  176.         else
  177.             PBRUN[j][0] = i; /* start of run */
  178.         for ( i++;
  179.               i < rowlen && 
  180.             ( !same_color( i, rows, the_hdr->bg_color,
  181.                      the_hdr->ncolors, bits ) ||
  182.               (the_hdr->alpha && rows[-1][i] != 0) );
  183.               i++)
  184.             ;            /* find the end of this run */
  185.         PBRUN[j][1] = i-1;    /* last in run */
  186.         j++;
  187.         }
  188.     nrun = j;
  189.     }
  190.     else
  191.     {
  192.     PBRUN[0][0] = 0;
  193.     PBRUN[0][1] = rowlen-1;
  194.     nrun = 1;
  195.     }
  196. #endif                /* FASTRUNS */
  197.     /* One final pass merges runs with fewer than 4 intervening pixels
  198.      * if the second run is longer than 255 pixels.  This is because
  199.      * the startup cost for such a run is 4 bytes.
  200.      */
  201.     if ( nrun > 1 )
  202.     {
  203.     for ( i = nrun - 1; i > 0; i-- )
  204.     {
  205.         if ( PBRUN[i][1] - PBRUN[i][0] > 255 &&
  206.          PBRUN[i-1][1] + 4 > PBRUN[i][0] )
  207.         {
  208.         PBRUN[i-1][1] = PBRUN[i][1];
  209.         for ( j = i; j < nrun - 1; j++ )
  210.         {
  211.             PBRUN[j][0] = PBRUN[j+1][0];
  212.             PBRUN[j][1] = PBRUN[j+1][1];
  213.         }
  214.         nrun--;
  215.         }
  216.     }
  217.     }
  218.  
  219.     if (nrun > 0)
  220.     {
  221.     if (the_hdr->priv.put.nblank > 0)
  222.     {
  223.         SkipBlankLines(the_hdr->priv.put.nblank);
  224.         the_hdr->priv.put.nblank = 0;
  225.     }
  226.     for ( mask = (the_hdr->alpha ? -1 : 0);
  227.           mask < the_hdr->ncolors;
  228.           mask++)            /* do all colors */
  229.     {
  230.         if ( ! bits[mask & 0xff] )
  231.         {
  232.         continue;
  233.         }
  234.         row = rows[mask];
  235.         SetColor(mask);
  236.         if (PBRUN[0][0] > 0)
  237.         {
  238.         SkipPixels(PBRUN[0][0], FALSE, FALSE);
  239.         }
  240.         for (j=0; j<nrun; j++)
  241.         {
  242.         state = DATA;
  243.         dstart = PBRUN[j][0];
  244.         dend = PBRUN[j][1];
  245.         for (i=dstart; i<=dend; i++)
  246.         {
  247.             switch(state)
  248.             {
  249.             case DATA:
  250.             if (i > dstart && runval == row[i])
  251.             {
  252.                 /* 2 in a row may be a run. */
  253.                 /* If odd data length, start with RUN1 */
  254.                 if ( ((i - dstart) % 2) == 0)
  255.                 state = RUN1;
  256.                 else
  257.                 state = RUN2;
  258.             }
  259.             else
  260.             {
  261.                 runval = row[i];    /* maybe a run starts here? */
  262.                 rstart = i;
  263.             }
  264.             break;
  265.         
  266.             case RUN4:
  267.             if (runval == row[i])
  268.             {
  269.                 /* If the following data might be longer
  270.                  * than 255 pixels then look for 8 in a
  271.                  * row, otherwise, 6 in a row is
  272.                  * sufficient.  Fake this by skipping to
  273.                  * state RUN5.
  274.                  */
  275.                 if ( dend - i > 255 )
  276.                 state  = RUN5;    /* Need some more. */
  277.                 else
  278.                 state = RUN7;    /* Next one makes a run. */
  279.                 
  280.             }
  281.             else
  282.             {
  283.                 state = DATA;    /* Nope, back to data */
  284.                 runval = row[i];    /* but maybe a new run here? */
  285.                 rstart = i;
  286.             }
  287.             break;
  288.  
  289.             case RUN1:
  290.             case RUN2:
  291.             case RUN3:
  292.             case RUN5:
  293.             case RUN6:
  294.             if (runval == row[i])
  295.             {
  296.                 /* Move to the next state. */
  297.                 state++;
  298.             }
  299.             else
  300.             {
  301.                 state = DATA;    /* Nope, back to data */
  302.                 runval = row[i];    /* but maybe a new run here? */
  303.                 rstart = i;
  304.             }
  305.             break;
  306.  
  307.  
  308.             case RUN7:
  309.             if (runval == row[i])    /* enough in a row for a run */
  310.             {
  311.                 state = INRUN;
  312.                 putdata(row + dstart, rstart - dstart);
  313. #ifdef FASTRUNS
  314. #ifdef LOCC
  315.                 /* Shortcut to find end of run! */
  316.                 i = dend - skpc( (char *)row + i, dend + 1 - i,
  317.                          runval );
  318. #else
  319.                 while ( row[++i] == runval && i <= dend)
  320.                 ; /* not quite so good, but not bad */
  321.                 i--;
  322. #endif /* LOCC */
  323. #endif /* FASTRUNS */
  324.             }
  325.             else
  326.             {
  327.                 state = DATA;        /* not a run, */
  328.                 runval = row[i];    /* but may this starts one */
  329.                 rstart = i;
  330.             }
  331.             break;
  332.         
  333.             case INRUN:
  334.             if (runval != row[i])    /* if run out */
  335.             {
  336.                 state = DATA;
  337.                 putrun(runval, i - rstart, FALSE);
  338.                 runval = row[i];    /* who knows, might be more */
  339.                 rstart = i;
  340.                 dstart = i;    /* starting a new 'data' run */
  341.             }
  342.             break;
  343.             }
  344.         }
  345.         if (state == INRUN)
  346.             putrun(runval, i - rstart, TRUE);    /* last bit */
  347.         else
  348.             putdata(row + dstart, i - dstart);
  349.  
  350.         if (j < nrun-1)
  351.             SkipPixels(
  352.                 PBRUN[j+1][0] - dend - 1,
  353.                 FALSE, state == INRUN);
  354.         else
  355.         {
  356.             if (rowlen - dend > 0)
  357.             SkipPixels(
  358.                 rowlen - dend - 1,
  359.                 TRUE, state == INRUN);
  360.         }
  361.         }
  362.  
  363.         if ( mask != the_hdr->ncolors - 1 )
  364.         NewScanLine(FALSE);
  365.     }
  366.     }
  367.  
  368.     /* Increment to next scanline */
  369.     the_hdr->priv.put.nblank++;
  370.  
  371.     /* flush every scanline */
  372.     fflush( the_hdr->rle_file );
  373. }
  374.  
  375.  
  376. /*****************************************************************
  377.  * TAG( rle_skiprow )
  378.  * 
  379.  * Skip rows in RLE file.
  380.  * Inputs:
  381.  *     the_hdr:        Header struct for RLE output file.
  382.  *      nrow:            Number of rows to skip.
  383.  * Outputs:
  384.  *     Increments the nblank field in the the_hdr struct, so that a Skiplines
  385.  *      code will be output the next time rle_putrow or rle_putraw is called.
  386.  * Assumptions:
  387.  *     Only effective when called between rle_putrow or rle_putraw calls (or
  388.  *      some other routine that follows the same conventions.
  389.  * Algorithm:
  390.  *    [None]
  391.  */
  392. void
  393. rle_skiprow( the_hdr, nrow )
  394. rle_hdr *the_hdr;
  395. int nrow;
  396. {
  397.     the_hdr->priv.put.nblank += nrow;
  398. }
  399.  
  400.  
  401. /*****************************************************************
  402.  * TAG( rle_put_init )
  403.  * 
  404.  * Initialize the header structure for writing scanlines. 
  405.  * Inputs:
  406.  *    [None]
  407.  * Outputs:
  408.  *     the_hdr:    Private portions initialized for output.
  409.  * Assumptions:
  410.  *    [None]
  411.  * Algorithm:
  412.  *    [None]
  413.  */
  414. void
  415. rle_put_init( the_hdr )
  416. register rle_hdr *the_hdr;
  417. {
  418.     the_hdr->dispatch = RUN_DISPATCH;
  419.  
  420.     if ( the_hdr->is_init != RLE_INIT_MAGIC )
  421.     {
  422.     the_hdr->cmd = "Urt";
  423.     the_hdr->file_name = "some file";
  424.     }
  425.     the_hdr->priv.put.nblank = 0;    /* Reinit static vars */
  426.     /* Would like to be able to free previously allocated storage,
  427.      * but can't count on a non-NULL value being a valid pointer.
  428.      */
  429.     PBRUN = NULL;
  430.     the_hdr->priv.put.fileptr = 0;
  431.  
  432.     /* Only save alpha if alpha AND alpha channel bit are set. */
  433.     if ( the_hdr->alpha )
  434.     the_hdr->alpha = (RLE_BIT( *the_hdr, -1 ) != 0);
  435.     else
  436.     RLE_CLR_BIT( *the_hdr, -1 );
  437. }
  438.  
  439. /*****************************************************************
  440.  * TAG( rle_put_setup )
  441.  * 
  442.  * Initialize for writing RLE, and write header to output file.
  443.  * Inputs:
  444.  *     the_hdr:    Describes output image.
  445.  * Outputs:
  446.  *     the_hdr:    Initialized.
  447.  * Assumptions:
  448.  *    Lots of them.
  449.  * Algorithm:
  450.  *    [None]
  451.  */
  452. void
  453. rle_put_setup( the_hdr )
  454. register rle_hdr * the_hdr;
  455. {
  456.     rle_put_init( the_hdr );
  457.     the_hdr->img_num++;        /* Count output images. */
  458.     Setup();
  459. }
  460.  
  461. /*ARGSUSED*/
  462. void
  463. DefaultBlockHook(the_hdr)
  464. rle_hdr * the_hdr;
  465. {
  466.                         /* Do nothing */
  467. }
  468.  
  469. /*****************************************************************
  470.  * TAG( rle_puteof )
  471.  * Write an EOF code into the output file.
  472.  */
  473. void
  474. rle_puteof( the_hdr )
  475. register rle_hdr * the_hdr;
  476. {
  477.     /* Don't puteof twice. */
  478.     if ( the_hdr->dispatch == NO_DISPATCH )
  479.     return;
  480.     PutEof();
  481.     fflush( the_hdr->rle_file );
  482.     /* Free storage allocated by rle_put_init. */
  483.     if ( PBRUN != NULL )
  484.     {
  485.     free( PBRUN );
  486.     PBRUN = NULL;
  487.     }
  488.     /* Signal that puteof has been called. */
  489.     the_hdr->dispatch = NO_DISPATCH;
  490. }
  491.  
  492. #ifndef FASTRUNS
  493. /*****************************************************************
  494.  * TAG( same_color )
  495.  * 
  496.  * Determine if the color at the given index position in the scan rows
  497.  * is the same as the background color.
  498.  * Inputs:
  499.  *     index:        Index to the pixel position in each row.
  500.  *    rows:        array of pointers to the scanlines
  501.  *    bg_color:   the background color
  502.  *    ncolors:    number of color elements/pixel
  503.  * Outputs:
  504.  *     TRUE if the color at row[*][i] is the same as bg_color[*].
  505.  * Assumptions:
  506.  *    [None]
  507.  * Algorithm:
  508.  *    [None]
  509.  */
  510. static int
  511. same_color( index, rows, bg_color, ncolors, bits )
  512. register rle_pixel *rows[];
  513. register int bg_color[];
  514. char *bits;
  515. {
  516.     register int i;
  517.  
  518.     for ( i = 0; i < ncolors; i++, bits++ )
  519.     if ( *bits &&
  520.          rows[i][index] != bg_color[i] )
  521.         return 0;
  522.     return 1;                /* all the same */
  523. }
  524. #endif /* !FASTRUNS */
  525.  
  526. /*****************************************************************
  527.  * TAG( findruns )
  528.  * 
  529.  * Find runs not a given color in the row.
  530.  * Inputs:
  531.  *     row:        Row of pixel values
  532.  *    rowlen:        Number of pixels in the row.
  533.  *    color:        Color to compare against.
  534.  *    nrun:        Number of runs already found (in different colors).
  535.  *    brun:        Runs found in other color channels already.
  536.  * Outputs:
  537.  *     brun:        Modified to reflect merging of runs in this color.
  538.  *    Returns number of runs in brun.
  539.  * Assumptions:
  540.  *
  541.  * Algorithm:
  542.  *     Search for occurences of pixels not of the given color outside
  543.  *    the runs already found.  When some are found, add a new run or
  544.  *    extend an existing one.  Adjacent runs with fewer than two
  545.  *    pixels intervening are merged.
  546.  */
  547. static int
  548. findruns( row, rowlen, color, nrun, brun )
  549. register rle_pixel *row;
  550. int rowlen, color, nrun;
  551. short (*brun)[2];
  552. {
  553.     int i = 0, lower, upper;
  554.     register int s, j;
  555.  
  556. #ifdef DEBUG
  557.     fprintf( stderr, "findruns( " );
  558.     for ( s = 0; s < rowlen; s++ )
  559.     fprintf( stderr, "%2x.%s", row[s], (s % 20 == 19) ? "\n\t" : "" );
  560.     if ( s % 20 != 0 )
  561.     fprintf( stderr, "\n\t" );
  562.     fprintf( stderr, "%d, %d, %d, \n\t", rowlen, color, nrun );
  563.     for ( j = 0; j < nrun; j++ )
  564.     fprintf( stderr, "(%3d,%3d) %s", brun[j][0], brun[j][1],
  565.         (j % 6 == 5) ? "\n\t" : "" );
  566.     fprintf( stderr, ")\n" );
  567. #endif
  568.  
  569.     while ( i <= nrun )
  570.     {
  571.     /* Assert: 0 <= i <= rowlen
  572.      * brun[i] is the run following the "blank" space being
  573.      * searched.  If i == rowlen, search after brun[i-1].
  574.      */
  575.  
  576.     /* get lower and upper bounds of search */
  577.  
  578.     if ( i == 0 )
  579.         lower = 0;
  580.     else
  581.         lower = brun[i-1][1] + 1;
  582.  
  583.     if ( i == nrun )
  584.         upper = rowlen - 1;
  585.     else
  586.         upper = brun[i][0] - 1;
  587.  
  588. #ifdef DEBUG
  589.     fprintf( stderr, "Searching before run %d from %d to %d\n",
  590.         i, lower, upper );
  591. #endif
  592.     /* Search for beginning of run != color */
  593. #if  defined(LOCC)&defined(vax)
  594.     s = upper - skpc( (char *)row + lower, upper - lower + 1, color ) + 1;
  595. #else
  596.     for ( s = lower; s <= upper; s++ )
  597.         if ( row[s] != color )
  598.         break;
  599. #endif
  600.  
  601.     if ( s <= upper )    /* found a new run? */
  602.     {
  603.         if ( s > lower + 1 || i == 0 ) /* disjoint from preceding run? */
  604.         {
  605. #ifdef DEBUG
  606.         fprintf( stderr, "Found new run starting at %d\n", s );
  607. #endif
  608.         /* Shift following runs up */
  609.         for ( j = nrun; j > i; j-- )
  610.         {
  611.             brun[j][0] = brun[j-1][0];
  612.             brun[j][1] = brun[j-1][1];
  613.         }
  614.         brun[i][0] = s;
  615.         nrun++;
  616.         }
  617.         else
  618.         {
  619.         i--;        /* just add to preceding run */
  620. #ifdef DEBUG
  621.         fprintf( stderr, "Adding to previous run\n" );
  622. #endif
  623.         }
  624.  
  625. #if defined(LOCC)&defined(vax)
  626.         s = upper - locc( (char *)row + s, upper - s + 1, color ) + 1;
  627. #else
  628.         for ( ; s <= upper; s++ )
  629.         if ( row[s] == color )
  630.             break;
  631. #endif
  632.         brun[i][1] = s - 1;
  633.  
  634. #ifdef DEBUG
  635.         fprintf( stderr, "Ends at %d", s - 1 );
  636. #endif
  637.         if ( s >= upper && i < nrun - 1 ) /* merge with following run */
  638.         {
  639.         brun[i][1] = brun[i+1][1];
  640.         /* move following runs back down */
  641.         for ( j = i + 2; j < nrun; j++ )
  642.         {
  643.             brun[j-1][0] = brun[j][0];
  644.             brun[j-1][1] = brun[j][1];
  645.         }
  646.         nrun--;
  647. #ifdef DEBUG
  648.         fprintf( stderr, ", add to next run" );
  649. #endif
  650.         }
  651. #ifdef DEBUG
  652.         putc( '\n', stderr );
  653. #endif
  654.     }
  655.     
  656.     /* Search in next space */
  657.     i++;
  658.     }
  659.  
  660.     return nrun;
  661. }
  662.  
  663.  
  664. /*****************************************************************
  665.  * TAG( rgb_to_bw )
  666.  * 
  667.  * Perform the NTSC Y transform on RGB data to get B&W data.
  668.  * Inputs:
  669.  *     red_row, green_row, blue_row:    Given RGB pixel data.
  670.  *    rowlen:        Number of pixels in the rows.
  671.  * Outputs:
  672.  *     bw_row:        Output B&W data.  May coincide with one of the
  673.  *            inputs.
  674.  * Assumptions:
  675.  *    [None]
  676.  * Algorithm:
  677.  *     BW = .30*R + .59*G + .11*B
  678.  */
  679. void
  680. rgb_to_bw( red_row, green_row, blue_row, bw_row, rowlen )
  681. rle_pixel *red_row;
  682. rle_pixel *green_row;
  683. rle_pixel *blue_row;
  684. rle_pixel *bw_row;
  685. int rowlen;
  686. {
  687.     register int x, bw;
  688.  
  689.     for (x=0; x<rowlen; x++)
  690.     {
  691.     /* 68000 won't store float > 127 into byte? */
  692.     /* HP compiler blows it */
  693.     bw = 0.5 + .30*red_row[x] + .59*green_row[x] + .11*blue_row[x];
  694.     bw_row[x] = bw;
  695.     }
  696. }
  697.  
  698. #ifdef LOCC
  699. /*ARGSUSED*/
  700. locc( p, l, c )
  701. register char *p;
  702. register int l;
  703. register int c;
  704. {
  705.     asm( "locc    r9,r10,(r11)" );
  706. #ifdef lint
  707.     c = (int) p;        /* why doesn't ARGSUSED work? */
  708.     l = c;
  709.     return l;            /* Needs return value, at least */
  710. #endif
  711. }
  712.  
  713. /*ARGSUSED*/
  714. skpc( p, l, c )
  715. register char *p;
  716. register int l;
  717. register int c;
  718. {
  719.     asm( "skpc r9,r10,(r11)" );
  720. #ifdef lint
  721.     c = (int) p;        /* why doesn't ARGSUSED work? */
  722.     l = c;
  723.     return l;            /* Needs return value, at least */
  724. #endif
  725. }
  726. #endif
  727.